﻿using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Reflection;
using Microsoft.AspNetCore.Http;
using System.Xml;
using Newtonsoft.Json;

namespace ChatBackend.Common.Filter
{
    public class ResultFilter : ActionFilterAttribute
    {
        /// <summary>
        /// 返回结果之后
        /// </summary>
        /// <param name="context"></param>
        public void OnResultExecuted(ResultExecutedContext context)
        {
        }

        /// <summary>
        /// 返回结果之前
        /// </summary>
        /// <param name="context"></param>
        public void OnResultExecuting(ResultExecutingContext context)
        {
            var setting = new JsonSerializerSettings
            {
                ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
                DateFormatString = "yyyy-MM-dd HH:mm:ss"
            };

            //标记了NonApiResultAttribute的方法不走ApiResult
            // 获取当前执行的方法

            var arrtCount = context.ActionDescriptor.EndpointMetadata.Where(x => x.GetType() == typeof(NoWrapperAttribute)).ToList();

            if (arrtCount.Count <= 0)
            {
                var actionResult = context.Result;
                var result = new ResponseResult<IActionResult> { Code = 200, Message = "OK" };

                if (context.HttpContext.Response.StatusCode == StatusCodes.Status401Unauthorized)
                {
                    result.Code = StatusCodes.Status401Unauthorized;
                    result.Message = "Unauthorized";
                }
                else if (actionResult is ObjectResult objectResult)
                {
                    result.Code = StatusCodes.Status200OK;
                    result.Message = objectResult.Value.ToString() ?? "";
                }
                else if (actionResult is EmptyResult emptyResult)
                {
                    result.Code = StatusCodes.Status200OK;
                }

                //返回结果之前
                context.Result = new ContentResult
                {
                    StatusCode = result.Code,
                    ContentType = "application/json",
                    Content = JsonConvert.SerializeObject(result, Newtonsoft.Json.Formatting.None, setting)
                };
            }
            else
            {
                var result = context.Result as ObjectResult;
                context.Result = new ContentResult
                {
                    StatusCode = context.HttpContext.Response.StatusCode,
                    ContentType = "application/json",
                    Content = JsonConvert.SerializeObject(result.Value, Newtonsoft.Json.Formatting.None, setting)
                };
            }
        }

        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
        public class NoWrapperAttribute : Attribute
        {
        }

        //定义返回状态码，用于判断返回结果是正常还是异常或者其他
        public enum ResultStatus
        {
            [Description("请求成功")]
            Success = 1,

            [Description("请求失败")]
            Fail = 0,

            [Description("请求异常")]
            Error = -1,
        }

        public class EnumHelper
        {
            /// <summary>
            /// 获取枚举的Description
            /// </summary>
            /// <param name="value">枚举值</param>
            /// <param name="nameInstend">当枚举没有定义的DescriptionAttribute，是否用枚举名代替，默认使用</param>
            /// <returns></returns>
            public static string GetDescription(Enum value, bool nameInstend = true)
            {
                Type type = value.GetType();
                string name = Enum.GetName(type, value);
                if (name == null)
                {
                    return null;
                }
                FieldInfo field = type.GetField(name);
                DescriptionAttribute attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
                if (attribute == null && nameInstend)
                {
                    return name;
                }
                return attribute?.Description;
            }
        }

        //返回结果泛型包装类
        public class ResponseResult<T>
        {
            /// <summary>
            /// 状态结果
            /// </summary>
            public ResultStatus Status { get; set; } = ResultStatus.Success;

            private string? _msg;

            public string? Message
            {
                get { return !string.IsNullOrEmpty(_msg) ? _msg : EnumHelper.GetDescription(Status); }
                set { _msg = value; }
            }

            /// <summary>
            /// 返回结果
            /// </summary>
            public T Data { get; set; }

            /// <summary>
            /// 状态码
            /// </summary>
            public int? Code { get; set; }

            /// <summary>
            /// 成功状态返回结果
            /// </summary>
            /// <param name="data">返回的数据</param>
            /// <returns></returns>
            public static ResponseResult<T> SuccessResult(T data)
            {
                return new ResponseResult<T> { Status = ResultStatus.Success, Data = data, Code = 200 };
            }

            /// <summary>
            /// 失败状态返回结果
            /// </summary>
            /// <param name="msg">失败信息</param>
            /// <returns></returns>
            public static ResponseResult<T> FailResult(string? msg = null)
            {
                return new ResponseResult<T> { Status = ResultStatus.Fail, Message = msg, Code = 400 };
            }

            /// <summary>
            /// 异常状态返回结果
            /// </summary>
            /// <param name="msg">异常信息</param>
            /// <returns></returns>
            public static ResponseResult<T> ErrorResult(string? msg = null)
            {
                return new ResponseResult<T> { Status = ResultStatus.Error, Message = msg, Code = 500 };
            }

            /// <summary>
            /// 自定义状态返回结果
            /// </summary>
            /// <param name="status"></param>
            /// <param name="data"></param>
            /// <param name="msg"></param>
            /// <returns></returns>
            public static ResponseResult<T> Result(ResultStatus status, T data, string? msg = null, int code = 200)
            {
                return new ResponseResult<T> { Status = status, Data = data, Message = msg, Code = code };
            }

            /// <summary>
            /// 隐式将T转化为ResponseResult<T>
            /// </summary>
            /// <param name="value"></param>
            public static implicit operator ResponseResult<T>(T value)
            {
                return new ResponseResult<T> { Data = value };
            }
        }
    }
}